package com.library.web.controller.library;


import com.library.common.annotation.Log;
import com.library.common.constant.HttpStatus;
import com.library.common.core.controller.BaseController;
import com.library.common.core.domain.AjaxResult;
import com.library.common.core.domain.BaseEntity;
import com.library.common.core.page.TableDataInfo;
import com.library.common.enums.BusinessType;
import com.library.common.utils.StringUtils;
import com.library.common.utils.poi.ExcelUtil;
import com.library.domain.BoBook;
import com.library.domain.BoBorrow;
import com.library.domain.BoIntegralHistory;
import com.library.domain.BoMembers;
import com.library.service.*;
import com.library.web.controller.vo.BorrowsModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.UUID;


/**
 * 图书借阅 信息操作处理
 *
 * @author wanghongjie
 * @date 2020-01-18
 */
@RestController
@RequestMapping("/library/boBorrow")
@Slf4j
public class BoBorrowController extends BaseController {
    private String prefix = "business/library/boBorrow";

    @Autowired
    private IBoBorrowService boBorrowService;

    /**
     * 图书管理Service类
     */
    @Autowired
    private IBoBookService boBookService;

    /**
     * 积分配置
     */
    @Autowired
    private IBoIntegralConfigService integralConfigService;
    /**
     * 会员管理类
     */
    @Autowired
    private IBoMembersService membersService;
    /**
     * 积分调整记录服务类
     */
    @Autowired
    private IBoIntegralHistoryService boIntegralHistoryService;

    /**
     * 查询图书借阅列表
     */
    @PreAuthorize("@ss.hasPermi('library:borrow:list')")
    @GetMapping("/list")
    public TableDataInfo list(BoBorrow boBorrow) {
        startPage();
        List<BoBorrow> list = boBorrowService.selectBoBorrowList(boBorrow);
        return getDataTable(list);
    }

    /**
     * 导出图书借阅列表
     */
    @PreAuthorize("@ss.hasPermi('library:borrow:export')")
    @Log(title = "图书借阅", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, BoBorrow boBorrow) {
        List<BoBorrow> list = boBorrowService.selectBoBorrowList(boBorrow);
        ExcelUtil<BoBorrow> util = new ExcelUtil<BoBorrow>(BoBorrow.class);
        util.exportExcel(response, list, "图书借阅数据");
    }

    /**
     * 获取图书借阅详细信息
     */
    @PreAuthorize("@ss.hasPermi('library:borrow:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") Long id) {
        return AjaxResult.success(boBorrowService.selectBoBorrowById(id));
    }


    /**
     * 新增保存图书借阅
     */
    @Log(title = "图书借阅", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    @Transactional
    public AjaxResult addSave(BoBorrow boBorrow) {
        boBorrow.setBorrowTime(new Date());
        // status 0 表示未归还 1 表示归还
        boBorrow.setStatus(BaseEntity.STATUS_0);
        //锁定图书状态
        BoBook boBook = boBookService.selectBoBookById(boBorrow.getBookId());
        //检查图书状态是否空闲
        if (BaseEntity.STATUS_1.equals(boBook.getBookStatus())) {
            return AjaxResult.error("该[ " + boBook.getBookName() + " ]图书已被借阅");
        }
        BoMembers boMembers = membersService.selectBoMembersById(boBorrow.getMembersId());
        if (null == boMembers) {
            return AjaxResult.error("用户信息不存在，请重新输入信息");
        }
        if (checkBoBorrowIsHas(boBorrow)) {
            return AjaxResult.error("该图书已经存在借阅信息，请归还后再次借阅");
        }
        boBook.setBookStatus(BaseEntity.STATUS_1);
        boBookService.updateBoBook(boBook);
        return toAjax(boBorrowService.insertBoBorrow(boBorrow));
    }

    /**
     * 检查图书借阅是否已经存在
     * 如果该图书未归还则 不允许借阅
     *
     * @param boBorrow 图书借阅信息
     * @return 状态
     */
    private boolean checkBoBorrowIsHas(BoBorrow boBorrow) {
        BoBorrow dbBoBorrow = boBorrowService.selectBoBorrowByBookIdAndStatus(boBorrow.getBookId());
        if (dbBoBorrow != null) {
            return true;
        }
        return false;
    }


    /**
     * 批量图书借阅
     *
     * @return
     */
    @Log(title = "图书借阅", businessType = BusinessType.INSERT)
    @PostMapping("/adds")
    @Transactional
    public AjaxResult addBorrows(@RequestBody BorrowsModel borrowsModel) {
        if (Objects.isNull(borrowsModel.getMembersId())) {
            return AjaxResult.error("用户信息为空，请重新选择！");
        }
        if (Objects.isNull(borrowsModel.getBookIds()) || borrowsModel.getBookIds().isEmpty()) {
            return AjaxResult.error("图书编号为空，请重新选择！");
        }
        for (Long bookId : borrowsModel.getBookIds()) {
            BoBorrow boBorrow = new BoBorrow();
            boBorrow.setBookId(bookId);
            boBorrow.setMembersId(borrowsModel.getMembersId());
            boBorrow.setBorrowDeposit(Integer.valueOf(borrowsModel.getMembersDeposit()));
            boBorrow.setDepositType(borrowsModel.getMembersDepositType());
            AjaxResult ajaxResult = addSave(boBorrow);
            if ((Integer) ajaxResult.get("code") != HttpStatus.SUCCESS) {
                log.error("book boBorrow is error ! bookId is {}", bookId);
                log.error("book boBorrow is error ! msg is {}", ajaxResult.get("msg"));
                //手动回滚事务
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ajaxResult;
            }
        }
        return AjaxResult.success();
    }

    /**
     * 修改图书借阅
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") Long id, ModelMap mmap) {
        BoBorrow boBorrow = boBorrowService.selectBoBorrowById(id);
        mmap.put("boBorrow", boBorrow);
        return prefix + "/edit";
    }


    @Log(title = "图书借阅", businessType = BusinessType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        try {
            return toAjax(boBorrowService.deleteUserByIds(ids));
        } catch (Exception e) {
            return error(e.getMessage());
        }
    }

    /**
     * 批量归还图书
     */
    @Log(title = "归还图书", businessType = BusinessType.UPDATE)
    @PostMapping("/returnBooks")
    @ResponseBody
    @Transactional
    public AjaxResult returnBooks(@RequestBody BorrowsModel borrowsModel) {
        if (Objects.isNull(borrowsModel.getMembersId())) {
            return AjaxResult.error("用户信息为空，请重新选择！");
        }
        if (Objects.isNull(borrowsModel.getBookIds()) || borrowsModel.getBookIds().isEmpty()) {
            return AjaxResult.error("图书编号为空，请重新选择！");
        }
        BoBorrow borrow = new BoBorrow();
        borrow.setMembersId(borrowsModel.getMembersId());
        BoBook boBook = new BoBook();
        StringBuilder stringBuffer = new StringBuilder();
        for (Long bookId : borrowsModel.getBookIds()) {
            BoBorrow boBorrow = new BoBorrow();
            boBorrow.setBookId(bookId);
            boBorrow.setMembersId(borrowsModel.getMembersId());
            BoBook book = boBookService.selectBoBookById(boBorrow.getBookId());
            stringBuffer.append("《").append(book.getBookName()).append("》");
            AjaxResult ajaxResult = returnBook(boBorrow);
            if ((Integer) ajaxResult.get("code") != HttpStatus.SUCCESS) {
                log.error("book returnBooks is error ! bookId is {}", bookId);
                log.error("book returnBooks is error ! msg is {}", ajaxResult.get("msg"));
                //手动回滚事务
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return ajaxResult;
            }
        }
        boBook.setBookName(stringBuffer.toString());
        borrow.setBoBook(boBook);
        //归还图书获取积分
        returnBooksBonusPoints(borrow);
        return AjaxResult.success();
    }


    /**
     * 批量归还图书
     */
    @Log(title = "图书续借", businessType = BusinessType.UPDATE)
    @PostMapping("/continueBooks")
    @ResponseBody
    @Transactional
    @SuppressWarnings("all")
    public AjaxResult continueBooks(@RequestBody BorrowsModel borrowsModel) {
        if (Objects.isNull(borrowsModel.getMembersId())) {
            return AjaxResult.error("用户信息为空，请重新选择！");
        }
        if (Objects.isNull(borrowsModel.getBookIds()) || borrowsModel.getBookIds().isEmpty()) {
            return AjaxResult.error("图书编号为空，请重新选择！");
        }
        reBooks(borrowsModel.getBookIds(), borrowsModel.getMembersId());
        return AjaxResult.success();
    }

    /**
     * 图书归还记录
     *
     * @param bookIds   图书ID
     * @param membersId 用户ID
     */
    private void reBooks(List<Long> bookIds, Long membersId) {
        BoBorrow borrow = new BoBorrow();
        borrow.setMembersId(membersId);
        List<BoBorrow> boBorrows = boBorrowService.selectBorrowListByMembersId(borrow);
        for (Long bookId : bookIds) {
            for (BoBorrow boBorrow : boBorrows) {
                if (boBorrow.getBookId().equals(bookId)) {
                    //图书续借标示
                    String uuId = UUID.randomUUID().toString();
                    boBorrow.setReturnTime(new Date());
                    boBorrow.setStatus("1");
                    boBorrow.setExt3(uuId);
                    boBorrowService.updateBoBorrow(boBorrow);
                    boBorrow.setBorrowTime(new Date());
                    boBorrow.setReturnTime(null);
                    boBorrow.setStatus("0");
                    boBorrow.setId(null);
                    boBorrowService.insertBoBorrow(boBorrow);
                }
            }
        }
    }

    /**
     * 归还图书，不记录积分
     *
     * @param boBorrow 图书
     * @return
     */
    private AjaxResult returnBook(BoBorrow boBorrow) {
        if (null == boBorrow.getBookId()) {
            return AjaxResult.error("图书归还异常，请联系系统管理员");
        }
        //释放图书状态为空闲
        BoBook boBook = boBookService.selectBoBookById(boBorrow.getBookId());
        //检查图书状态是否锁定
        if (BaseEntity.STATUS_0.equals(boBook.getBookStatus())) {
            return AjaxResult.error("该[ " + boBook.getBookName() + " ]图书尚未借出，不可归还");
        }
        boBorrow.setStatus(BaseEntity.STATUS_0);
        boBook.setBookStatus(BaseEntity.STATUS_0);
        BoBorrow resBorrow = boBorrowService.selectBoBorrowByMembersIdAndBookId(boBorrow);
        if (null == resBorrow) {
            return AjaxResult.error("该[ " + boBook.getBookName() + " ]图书未借阅给该用户，请核对借阅信息！");
        }
        boBorrow = resBorrow;
        //设置图书状态为归还
        boBorrow.setReturnTime(new Date());
        boBorrow.setStatus(BaseEntity.STATUS_1);
        boBookService.updateBoBook(boBook);
        return toAjax(boBorrowService.updateBoBorrow(boBorrow));
    }


    /**
     * 归还图书
     */
    @Log(title = "归还图书", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(BoBorrow boBorrow) {
        if (null == boBorrow.getBookId()) {
            return AjaxResult.error("图书归还异常，请联系系统管理员");
        }
        //释放图书状态为空闲
        BoBook boBook = boBookService.selectBoBookById(boBorrow.getBookId());
        //检查图书状态是否锁定
        if (BaseEntity.STATUS_0.equals(boBook.getBookStatus())) {
            return AjaxResult.error("该[ " + boBook.getBookName() + " ]图书尚未借出，不可归还");
        }
        boBook.setBookStatus(BaseEntity.STATUS_0);
        boBorrow.setStatus(BaseEntity.STATUS_0);
        BoBorrow resBorrow = boBorrowService.selectBoBorrowByMembersIdAndBookId(boBorrow);
        if (null == resBorrow) {
            return AjaxResult.error("该[ " + boBook.getBookName() + " ]图书未借阅给该用户，请核对借阅信息！");
        }
        boBorrow = resBorrow;
        //设置图书状态为归还
        boBorrow.setStatus(BaseEntity.STATUS_1);
        boBorrow.setReturnTime(new Date());
        boBookService.updateBoBook(boBook);
        //归还图书获取积分
        returnBooksBonusPoints(boBorrow);
        return toAjax(boBorrowService.updateBoBorrow(boBorrow));
    }

    /**
     * 根据用户查询借阅信息
     *
     * @param boBorrow
     * @return
     */
    @GetMapping("/selectReturnBooksByMembers")
    public AjaxResult selectReturnBooksByMembers(BoBorrow boBorrow) {
        if (StringUtils.isEmpty(boBorrow.getMembersId().toString())) {
            return AjaxResult.error("用户信息错误");
        }
        List<BoBorrow> boBorrows = boBorrowService.selectBorrowListByMembersId(boBorrow);
        AjaxResult result = new AjaxResult();
        return Objects.requireNonNull(result.put("code", HttpStatus.SUCCESS)).put("data", boBorrows);
    }

    /**
     * 归还图书奖励积分
     */
    private void returnBooksBonusPoints(BoBorrow boBorrow) {
        //图书借阅奖励积分
        int i = integralConfigService.selectBoIntegralConfigByOtherNumber();
        Long membersId = boBorrow.getMembersId();
        BoMembers members = membersService.selectBoMembersById(membersId);
        if (null != members) {
            int availableIntegral = 0;
            int level = 0;
            if (null != members.getAvailableIntegral()) {
                availableIntegral = members.getAvailableIntegral();
            }
            if (null != members.getIntegralLevel()) {
                level = members.getIntegralLevel();
            }
            members.setAvailableIntegral(availableIntegral + i);
            if (i > 0) {
                members.setIntegralLevel(level + i);
            }
            //记录积分调整信息
            recordIntegral(boBorrow);
            membersService.updateBoMembers(members);
        }
    }

    /**
     * 记录积分调整记录
     */
    private void recordIntegral(BoBorrow boBorrow) {
        BoIntegralHistory boIntegralHistory = new BoIntegralHistory();
        //图书借阅奖励积分
        int i = integralConfigService.selectBoIntegralConfigByOtherNumber();
        Long membersId = boBorrow.getMembersId();
        BoMembers members = membersService.selectBoMembersById(membersId);
        boIntegralHistory.setMembersId(membersId);
        boIntegralHistory.setUserId(getUsername());
        boIntegralHistory.setAdjustType("2");
        boIntegralHistory.setAdjustReason("归还[" + boBorrow.getBoBook().getBookName() + "]获取积分");
        boIntegralHistory.setAdjustNumber(i);
        if (null != members) {
            int availableIntegral = 0;
            if (null != members.getAvailableIntegral()) {
                availableIntegral = members.getAvailableIntegral();
            }
            boIntegralHistory.setBeforeAdjust(availableIntegral);
            boIntegralHistory.setAfterAdjust(availableIntegral + i);
        }
        boIntegralHistoryService.insertBoIntegralHistory(boIntegralHistory);
    }


}
